from django.shortcuts import HttpResponse, render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect, Http404
from google.appengine.api import users, mail
import forms as appforms
from models import *
from whatyou.lib.utils import *
import datetime
import operator



def homepage(request):
    # Users
    user = users.get_current_user()
    person = get_or_create_person(user)
    # Forms
    form = appforms.PostForm()
    if person:
        profile = {"friendly_name": person.friendly_name, "gender": person.gender}
        update_profile_form = appforms.UpdateProfileForm(profile)
    else:
        update_profile_form = appforms.UpdateProfileForm()
    # Output
    try:
        latest_update = Update.all().order("-finish_time").order("-start_time").filter("finish_time >", datetime.datetime.now()).fetch(1)[0]
    except IndexError:
        latest_update = None
    verbs = Verb.all().order("-used_count").fetch(5)
    title_verb = "Up To?"
    if len(verbs) > 0:
        verb_name = verbs[0].name
        if verb_name[-3:] == "ing":
            title_verb = verb_name
    # Status Updates
    user_updates = []
    friends = []
    if person:
        user_updates = person.future_updates(10)
        friends = person.friends()
    for friend in friends:
        user_updates.extend(friend.future_updates(5))
    user_updates.sort(key=operator.attrgetter("finish_time"))
    return respond(request, user, "homepage.html", {"form":form, "update_profile_form":update_profile_form, "latest_update":latest_update, "user_updates":user_updates, "friends":friends, "verbs":verbs, "title_verb":title_verb})

def info_page(request, page_name):
    user = users.get_current_user()
    return respond(request, user, "info/%s.html" % page_name)

def create_update(request):
    # Users
    user = users.get_current_user()
    if not user: return HttpResponseRedirect(users.create_login_url("/"))
    person = get_or_create_person(user)
    # Postback
    if request.method == "POST" and user:
        posts = request.POST
        form = appforms.PostForm(request.POST)
        if form.is_valid():
            verb_input = form.cleaned_data["verb"]
            body_input = form.cleaned_data["body"]
            finish_time_input = form.cleaned_data["finish_time"]
            deltas = finish_time_input.split(":")
            years, weeks, days, hours, minutes = int(deltas[0]), int(deltas[1]), int(deltas[2]), int(deltas[3]), int(deltas[4])
            years_as_weeks = years * 52
            td = datetime.timedelta(weeks=weeks+years_as_weeks, days=days, hours=hours, minutes=minutes)
            finish_time = datetime.datetime.now() + td
            # Verbs
            verb = get_or_create_verb(verb_input.lower())
            # Update
            update = Update(verb=verb, body=body_input, finish_time=finish_time, owner=person)
            update.put()
            # Send Emails
            followers = Friendship.all().filter("them =", person)
            subject = "WhatYou: %s is %s %s" % (person.user.nickname(), verb.name, body_input)
            body = "New Update\n\n" + "%s is %s %s" % (person.user.nickname(), verb.name, body_input)
            from_address = person.user.email()
            for follower in followers:
                address = follower.me.user.email()
                message = mail.EmailMessage(sender=from_address, to=address, subject=subject, body=body)
                message.send()
            # Update metadata
            verb.used_count += 1
            verb.put()
            person.update_count += 1
            person.put()
    return HttpResponseRedirect("/")

def view_update(request, update_key):
    # Users
    user = users.get_current_user()
    person = get_or_create_person(user)
    # Update
    try:
        update = db.get(update_key)
    except db.BadKeyError:
        raise Http404
    return respond(request, user, "view_update.html", {"update":update})

def update_action(request, action, key, value):
    # Users
    user = users.get_current_user()
    if not user: return HttpResponseRedirect(users.create_login_url("/"))
    person = get_or_create_person(user)
    # Validation
    valid_actions = ("delete", "expire",)
    if not action in valid_actions:
        raise Http404
    try:
        update = db.get(key)
    except db.BadKeyError:
        raise Http404
    else:
        if update.owner.user == person.user:
            if action == "delete":
                    if update.verb.used_count > 0:
                        update.verb.used_count = update.verb.used_count - 1
                        update.verb.put()
                    update.delete()
            if action == "expire":
                    update.finish_time = datetime.datetime.now()
                    update.put()
    return HttpResponseRedirect("/")

def view_friend(request, friend_key):
    # Users
    user = users.get_current_user()
    if not user: return HttpResponseRedirect(users.create_login_url("/"))
    person = get_or_create_person(user)
    # Friend
    your_friend = db.get(friend_key)
    your_friend_updates = your_friend.updates.order("-finish_time").filter("finish_time >", datetime.datetime.now())
    friendship = Friendship.all().filter("me = ", person).filter("them = ", your_friend).fetch(1)[0]
    # Postback
    if request.method == "POST":
        form = appforms.EditFriendForm(request.POST)
        if form.is_valid():
            friendship.notify_by_email = form.cleaned_data["notify_by_email"]
            friendship.put()
    else:
        form = appforms.EditFriendForm({"notify_by_email":friendship.notify_by_email})
    # Output
    return respond(request, user, "view_friend.html", {"your_friend":your_friend, "your_friend_updates":your_friend_updates, "form":form})

# require login
def add_friend(request):
    # Users
    user = users.get_current_user()
    if not user: return HttpResponseRedirect(users.create_login_url("/"))
    person = get_or_create_person(user)
    # Postback
    your_friend_count = 0
    if request.method == 'POST':
        form = appforms.AddFriendForm(request.POST)
        if form.is_valid():
            your_friend_email = form.cleaned_data["email_address"]
            your_friend_notify_by_email = form.cleaned_data["notify_by_email"]
            your_friend_user = users.User(your_friend_email)
            your_friend_person = get_or_create_person(your_friend_user)
            your_friend_count = Friendship.all().filter("me =", person).filter("them = ", your_friend_person).count()
            if your_friend_count == 0:
                friendship = Friendship(me=person, them=your_friend_person, notify_by_email=your_friend_notify_by_email).put()
                return respond(request, user, "add_friend_successful.html")
    else:
        form = appforms.AddFriendForm()
    return respond(request, user, "add_friend.html", {"form":form, "your_friend_count":your_friend_count})

def view_person(request, key_name):
    # User
    user = users.get_current_user()
    person = get_or_create_person(user)
    another_person = db.get(db.Key(key_name))
    updates = another_person.updates.order("-finish_time").filter("finish_time >", datetime.datetime.now())
    # Output
    return respond(request, user, "view_person.html", {"another_person":another_person, "updates":updates})

def list_people_that_are(request, update_key_name):
    # User
    user = users.get_current_user()
    person = get_or_create_person(user)
    update = db.get(db.Key(update_key_name))
    updates = (Update.all()
              .order("finish_time")
              .filter("finish_time >", datetime.datetime.now())
              .filter("verb =",update.verb)
              .filter("body =",update.body)
              .fetch(10))

    title = "People currently " + update.verb.__unicode__() + " " + update.body

    # Output
    return respond(request, user, "list_people.html", {"title":title, "updates":updates})

def list_people_that_have_been(request, update_key_name):
    pass

def update_profile(request):
    user = users.get_current_user()
    if not user: return HttpResponseRedirect(users.create_login_url("/"))
    person = get_or_create_person(user)
    # Postback
    if request.method == "POST":
        form = appforms.UpdateProfileForm(request.POST)
        if form.is_valid():
            form_friendly_name = form.cleaned_data["friendly_name"]
            form_gender = form.cleaned_data["gender"].lower()
            if form_friendly_name != "":
                person.friendly_name = form_friendly_name
            if form_gender in ("m", "f"):
                person.gender = form_gender
            person.put()
    return HttpResponseRedirect("/")

## AJAX ##

def ajax_get_verbs(request):
    user = users.get_current_user()
    verbs = Verb.all().order("-used_count").fetch(25)
    return respond(request, user, "ajax/get_verbs.html", {"verbs":verbs})

def ajax_get_latest_update(request):
    user = users.get_current_user()
    try:
        latest_update = Update.all().order("-start_time").fetch(1)[0]
    except IndexError:
        latest_update = None
    return respond(request, user, "ajax/latest_update.html", {"latest_update":latest_update})

## RSS ##

def rss_updates(request, person_key=None, verb_name=None):
    # User
    user = users.get_current_user()
    # Person
    person = None
    if person_key:
        try:
            person = db.get(person_key)
        except db.BadKeyError:
            pass
    # Verb
    verb = None
    if verb_name:
        try:
            verb = Verb.all().filter("name = ", str(verb_name).lower()).fetch(1)[0]
        except IndexError:
            pass
    # Updates
    try:
        updates = Update.all().order("-finish_time").order("-start_time").filter("finish_time >", datetime.datetime.now())
        if person:
            updates.filter("owner = ", person)
        if verb:
            updates.filter("verb = ", verb)
        updates.fetch(50)
    except IndexError:
            updates = None
    # Output
    title_for, title_doing = "", ""
    if person:
        title_for = "%s" % (person.friendly_name)
    if verb:
        title_doing = "(verb: %s)" % (verb.name)
    title = "%s %s" % (title_for, title_doing)
    description = "WhatYou Latest Updates %s %s" % (title_for, title_doing)
    return respond(request, user, "services/rss_generic.xml", {"items":updates, "title":title, "description":description})